package com.hotelsystem.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hotelsystem.pojo.*;
import com.hotelsystem.service.*;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/orders")
public class OrdersController {

    @Resource(name = "ordersServiceImpl")
    private OrdersService ordersService;

    @Resource(name = "orderDetailServiceImpl")
    private OrderDetailService orderDetailService;

    @Resource(name = "roomTypeServiceImpl")
    private RoomTypeService roomTypeService;

    @Resource(name = "customerServiceImpl")
    private CustomerService customerService;

    @Resource(name = "roomServiceImpl")
    private RoomService roomService;

    /**
     * 按条件查询预定信息或全部信息并分页
     * @param name  客户姓名
     * @param idNumber 身份证号
     * @param typeName 房型名称
     * @param roomId 房间号
     * @param orderStatus 订单状态
     * @param pageNum 当前第几页
     * @param orderState 是去预订页面还是入住页面
     * @param model
     * @return
     */
    @RequestMapping("/getOrdersList")
    public String getOrdersList(@ModelAttribute(name = "name",binding = false) String name,
                                 @ModelAttribute(name = "idNumber",binding = false) String idNumber,
                                 @ModelAttribute(name = "typeName",binding = false) String typeName,
                                 @ModelAttribute(name = "roomId",binding = false) String roomId,
                                 @ModelAttribute(name = "orderStatus",binding = false) String orderStatus,
                                 @RequestParam("pageNum") Integer pageNum,
                                 @RequestParam("orderState") String orderState,
                                 Model model, HttpSession session){
        Employee emp = null;
        Map<String,Object> map = null;
        List<Orders> ordersList = null;
        try {
            //设置当前页和每页数量
            PageHelper.startPage(pageNum,4);
            //设置查询条件
            map = new HashMap<>();
            map.put("name",name);
            map.put("idNumber",idNumber);
            map.put("typeName",typeName);
            map.put("roomId",roomId);
            map.put("status", orderState.equals("预订中") ? Arrays.asList("2"): orderStatus.equals("0") ? Arrays.asList("1","2","8","9"):Arrays.asList(orderStatus));
            ordersList = ordersService.list(map);
            //获取PageInfo对象，该对象封装的分页的相关信息
            PageInfo<Orders> pageInfo = new PageInfo<>(ordersList);
            model.addAttribute("pageInfo",pageInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return orderState.equals("预订中") ? "stay/reserve/reserveList" : orderState.equals("入住结算") ? "stay/settleAccounts/settleAccounts":"stay/checkIn/checkInList";
    }

    /**
     * 取消预定
     * @param roomId
     * @param roomTypeId
     * @param ordersId
     * @param statusName
     * @param session
     * @return
     */
    @PostMapping("/updateOrderStatus")
    @ResponseBody
    public Map<String,Object> updateOrderStatus(String roomId,Integer roomTypeId,String ordersId, String statusName, HttpSession session){
        Map<String,Object> data = new HashMap<>();
        try {
            //修改订单状态
            Integer result = ordersService.updateOrderStatus(roomId,roomTypeId,ordersId, statusName);
            data.put("message",result > 0 ? "取消预订成功": "取消预订失败");
            data.put("state",200);
        } catch (Exception e) {
            e.printStackTrace();
            data.put("message","取消预订失败");
            data.put("state",500);
        }
        return data;
    }


    /**
     * 去预订或入住页面并默认将第一个类型的房间信息显示
     * @param model
     * @return
     */
    @GetMapping("/goToAddReserveOrCheckInRegister")
    public String goToAddReserveOrCheckInRegister(Model model,@RequestParam("statusName") String statusName){
        try {
            //查询全部房型信息
            List<RoomType> roomTypes = roomTypeService.listByTypeNameAndStatus(null,null);
            if ("预订".equals(statusName)){
                //获取每个类型下可预订的房间数
                for (RoomType roomType : roomTypes) {
                    roomType.setUsable(0);
                    for (Room room : roomType.getRooms()) {
                        if ("可预订".equals(room.getStatus().getStatusName())){
                            roomType.setUsable(roomType.getUsable() + 1);
                        }
                    }
                }
            }else{
                //获取每个类型下可预订与可入住的房间数
                for (RoomType roomType : roomTypes) {
                    roomType.setUsable(0);
                    for (Room room : roomType.getRooms()) {
                        if ("可预订".equals(room.getStatus().getStatusName()) || "可入住".equals(room.getStatus().getStatusName())){
                            roomType.setUsable(roomType.getUsable() + 1);
                        }
                    }
                }
            }
            //默认使用查询所有房型的第一个房型的房间信息
            List<RoomType> rooms = roomTypeService.listByTypeNameAndStatus(roomTypes.get(0).getTypeName(),"预订".equals(statusName) ? new String[]{"可预订"}:new String[]{"可预订","可入住"});
            model.addAttribute("roomTypes",roomTypes);
            model.addAttribute("rooms",(rooms.size() == 0) ? new ArrayList<Room>() : rooms.get(0).getRooms());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //根据状态决定去哪个页面
        return "预订".equals(statusName) ? "stay/reserve/addReserve" : "stay/checkIn/checkInRegister";
    }

    /**
     * 获取指定房型下的房间信息
     * @param typeName 房型名称
     * @return
     */
    @PostMapping("/getRoomByTypeName")
    @ResponseBody
    public List<Room> getRooms(String typeName,@RequestParam("statusName") String statusName){
        List<RoomType> roomTypes = null;
        try {
            roomTypes = roomTypeService.listByTypeNameAndStatus(typeName,"预订".equals(statusName) ? new String[]{"可预订"}:new String[]{"可预订","可入住"});
        } catch (Exception e) {
            e.printStackTrace();
        }
        //如果roomTypes为零表示没房间直接创建一个新集合
        return (roomTypes.size() == 0) ? new ArrayList<Room>() : roomTypes.get(0).getRooms();
    }

    /**
     * 根据身份证号模糊查询客户信息
     * @param idNumber 身份证号
     * @return
     */
    @PostMapping("/getCustomersByIdNumber")
    @ResponseBody
    public List<Customer> getCustomersByIdNumber(@RequestParam("idNumber") String idNumber){
        if (idNumber.equals("")) idNumber = null; //为了防止文本框完全删除时查询出全部数据
        List<Customer> customers = null;
        try {
            customers = customerService.list(idNumber);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return customers;
    }

    /**
     *  根据身份证号查询客户信息
     * @param idNumber 身份证号
     * @return
     */
    @PostMapping("/getCustomerByIdNumber")
    @ResponseBody
    public Customer getCustomerByIdNumber(@RequestParam("idNumber") String idNumber){
        Customer customer = null;
        try {
            customer = customerService.get(idNumber);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return customer;
    }

    /**
     * 根据身份证号查询预订中和入住中的订单
     * 如果有则不让再预订或入住房间
     * 即一张身份证只能预订或入住一间房间
     * @param conditionMap
     * @return
     */
    @PostMapping("/getOrdersByIdNumber")
    @ResponseBody
    public List<Orders> getOrdersByIdNumber(String idNumber,String ordersState,Map<String,Object> conditionMap){
        List<Orders> list = null;
        conditionMap.put("idNumber",idNumber);
        conditionMap.put("status","入住".equals(ordersState) ? Arrays.asList("1"):Arrays.asList("1","2"));
        try {
            list = ordersService.list(conditionMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 添加预订信息
     * 如果当前客户为老客户则直接添加预订信息
     * 否则先添加客户信息在添加预订信息
     * 并修改房间状态和房型相关信息
     * @param orders
     * @param session
     * @return
     */
    @RequestMapping("/addReserve")
    @ResponseBody
    public Boolean addReserve(Orders orders,HttpSession session){
        Boolean result = null;
        try {

            Integer count = ordersService.insert(orders);//添加订单
            result = count > 0 ? true : false;
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }

    /**
     * 删除订单
     * 只能删除状态为：已结算离店和取消预订的订单
     * @return
     */
    @PostMapping("/deleteOrders")
    @ResponseBody
    public Map<String,Object> deleteOrders(@RequestParam("ordersId") String ordersId,
                                              @RequestParam("statusId") Integer statusId,
                                              @RequestParam("statusName") String statusName,
                                              HttpSession session){
        Map<String,Object> map = new HashMap<>();
        if (!(statusId == 8 || statusId == 9)){
            map.put("message","抱歉当前订单正在："+ statusName +" 不可删除");
            map.put("state",500);
        }else {
            try {
                Integer result = ordersService.delete(ordersId);
                map.put("message",result > 0 ? "删除成功":"删除失败");
                map.put("state",200);
            } catch (Exception e) {
                e.printStackTrace();
                map.put("message","删除失败");
                map.put("state",500);
            }
        }
        return map;
    }

    /**
     * 根据身份证号模糊查询订单和客户信息，未下单的客户一并查询出来
     * @param idNumber
     * @return
     */
    @RequestMapping("/getOrdersOrCustomerInfos")
    @ResponseBody
    public List<Orders> getOrdersOrCustomerInfos(@RequestParam("idNumber") String idNumber){
        if (idNumber.equals("")) idNumber = null; //为了防止文本框完全删除时查询出全部数据
        List<Orders> orders = null; //原数据
        List<Orders> newOrders = new ArrayList<>();//过滤后的数据
        boolean result = false; //标记是否还有预订中或入住中的订单
        try {
            orders = ordersService.listByOrdersStatus(idNumber);
        } catch (Exception e) {
            e.printStackTrace();
        }
        /* 由于查询出来的是全部数据，需要将原有数据过滤 */
        //获取全部的身份证号
        Set<String> idNumbers = orders.stream().map(order -> order.getCustomer().getIdNumber()).collect(Collectors.toSet());
        //根据身份证号来验证订单集合里的合法性，实现过滤数据
        for (String number : idNumbers) {
            for (Orders order : orders) {
                //如果身份证号相同并且状态对象不为空表示当前客户有过订单
                if (number.equals(order.getCustomer().getIdNumber()) && order.getStatus() != null) {
                    /*如果订单状态为预订中或入住中直接添加到新集合并结束循环，因为预订中或入住中的订单一定只有一个，
                      如果后面还有取消预订等订单没必要添加进去主要以预订中或入住中为主*/
                    if("预订中".equals(order.getStatus().getStatusName()) || "入住中".equals(order.getStatus().getStatusName())){
                        newOrders.add(order);
                        break;
                    }
                    /*
                        如果订单状态为取消预订或已结算离店,由于查询出全部数据的顺序是乱的，还需进一步验证后面是否有预订中或入住中的订单
                        如果有则直接添加预订中或入住中的订单并结束循环，取消预订或已结算离店的则不添加
                        如果没有则添加取消预订或已结算离店的订单并结束循环,如果这两个同时存在只需要添加任意一个即可因为前台做了处理将取消预订和已结算离店的订单合并成一个
                     */
                    if ("取消预订".equals(order.getStatus().getStatusName()) || "已结算离店".equals(order.getStatus().getStatusName())){
                        for (Orders order1 : orders) {
                            if (number.equals(order1.getCustomer().getIdNumber()) && order1.getStatus() != null) {
                                if ("预订中".equals(order1.getStatus().getStatusName()) || "入住中".equals(order1.getStatus().getStatusName())) {
                                    newOrders.add(order1);
                                    result = true;
                                    break;
                                }
                            }
                            result = false;
                        }
                        if (!result) newOrders.add(order);
                        break;
                    }
                }
                //如果身份证号相同并且订单编号为空表示当前客户从来没有过订单则直接添加并结束循环，因为每个客户如果没有过订单的数据只可能有一条
                if (number.equals(order.getCustomer().getIdNumber()) && order.getOrdersId() == null) {
                    newOrders.add(order);
                    break;
                }
            }
        }
        return newOrders;
    }

    /**
     * 根据身份证号查询订单
     * @param idNumber
     * @return
     */
    @RequestMapping("/getOrdersOrCustomerInfo")
    @ResponseBody
    public Orders getOrdersOrCustomerInfo(@RequestParam("idNumber") String idNumber){
        return getOrdersOrCustomerInfos(idNumber).get(0);
    }

    /**
     * 登记入住
     * @param orders
     * @param orderDetail
     * @param session
     * @return
     */
    @RequestMapping("/addCheckInRegisterOrders")
    @ResponseBody
    public Boolean addCheckInRegisterOrders(Orders orders,OrderDetail orderDetail,HttpSession session){
        Boolean result = null;
        try {
            Integer count = ordersService.insertCheckInRegister(orders,orderDetail);//添加订单
            result = count > 0 ? true : false;
        } catch (Exception e) {
            e.printStackTrace();
            result = false;
        }
        return result;
    }

    /**
     * 查看订单明细
     * @param ordersId
     * @param session
     * @return
     */
    @PostMapping("/getOrderDetailInfo")
    @ResponseBody
    public List<OrderDetail> getOrderDetailInfo(@RequestParam("ordersId") String ordersId,HttpSession session){
        List<OrderDetail> orderDetails = null;
        try {
            orderDetails = orderDetailService.list(ordersId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return orderDetails;
    }

    /**
     * 根据订单编号模糊查询入住中订单信息
     */
    @PostMapping("/getOrdersByOrdersId")
    @ResponseBody
    public List<Orders> getOrdersByOrdersId(@RequestParam("ordersId") String ordersId){
        if (ordersId.equals("")) ordersId = null; //为了防止文本框完全删除时查询出全部数据
        try {
            return ordersService.listByOrdersId(ordersId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 添加账单
     * @param orderDetail
     * @param session
     * @return
     */
    @PostMapping("/addOrderDetail")
    @ResponseBody
    public Boolean addOrderDetail(OrderDetail orderDetail,HttpSession session){
        Integer result = 0;
        try {
            result = orderDetailService.insert(orderDetail);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result > 0 ? true : false;
    }

    /**
     * 付款操作
     * @param ordersId
     * @return
     */
    @PostMapping("/payment")
    @ResponseBody
    public Boolean payment(@RequestParam("ordersId") String ordersId){
        Integer result = 0;
        try {
            //获取原来数据修改已支付金额为总金额
            Orders orders = ordersService.listByOrdersId(ordersId).get(0);
            orders.setRepayMoney(orders.getTotalMoney());
            result = ordersService.updateAll(orders);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result > 0 ? true : false;
    }

    /**
     * 退房
     * @param ordersId
     * @param roomId
     * @param roomTypeId
     * @return
     */
    @PostMapping("/checkOut")
    @ResponseBody
    public Boolean checkOut(@RequestParam("ordersId") String ordersId,
                              @RequestParam("roomId") String roomId,
                              @RequestParam("roomTypeId") Integer roomTypeId,
                              HttpSession session){
        Integer result = 0;
        try {
            result = ordersService.checkOut(ordersId,roomId,roomTypeId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result > 0 ? true : false;
    }

}